package kk.orm;

import java.util.ArrayList;
import java.util.List;

import kk.orm.table.TableInfo;
import kk.orm.util.ClassUtil;
import kk.orm.util.CursorUtils;
import kk.orm.util.FieldUtil;
import kk.orm.util.SQLBuilder;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

@SuppressWarnings("unused")
public class DB {

	private static boolean			DEBUG	= true;
	private static final int		VERSION	= 1;
	private static DB				myDb;
	private static SQLiteHelpder	sqliteHelpder;
	private Context					mContext;

	/**
	 * 在写表时调用sqliteOpenHelper..getWritableDatabase()，在读表时候调用sqliteOpenHelper..getReadableDatabase()，getReadableDatabase性能更优。
	 */
	private SQLiteDatabase			db;

	private class SQLiteHelpder extends SQLiteOpenHelper {

		public SQLiteHelpder(Context context) {
			super(context, SQLiteHelpder.class.getName(), null, VERSION);
		}

		@Override
		public void onCreate(SQLiteDatabase db) {}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
	}

	private DB(Context context) {
		mContext = context;
		sqliteHelpder = new SQLiteHelpder(context);
		db = sqliteHelpder.getWritableDatabase();
	}

	public synchronized static DB getInstance(Context context) {
		if (myDb == null || (myDb != null && myDb.db != null && !myDb.db.isOpen())) {
			myDb = new DB(context);
		}

		return myDb;
	}

	/** 设置 是否Log SQL信息 */
	public static void setDEBUG(boolean dEBUG) {
		DEBUG = dEBUG;
	}

	/**
	 * 开始事务<br>
	 * 多个sql操作同时进行，可采取事务方式提交<br>
	 * 
	 * @see {@linkplain #commitTransaction()}
	 */
	public void beginTransaction() {
		db.beginTransaction();
	}

	/***
	 * 提交事务,一次执行多个sql语句,提高效率<br>
	 * 调用前，先调用{@linkplain #beginTransaction()}，在调用{@linkplain save()} {@linkplain delete()}等，最后调用此方法，sql才会被执行
	 */
	public void commitTransaction() {
		db.setTransactionSuccessful();
		db.endTransaction();
	}

	/**
	 * 保存entity表
	 * 
	 * @param entity
	 */
	public void save(Object entity) {
		// 情况1，无论id=x，都按自增长insert (如果需要按某个id插入，调用其他函数)
		checkTableExist(entity.getClass());
		execSQL(SQLBuilder.getInsertSQL(entity));
	}

	/** 删除表的某个对象(如果没有where，则以id为where) */
	public void delete(Object entity) {
		checkTableExist(entity.getClass());
		execSQL(SQLBuilder.getDeleteSQL(entity));
	}

	/** 注意：因为sql本身不支持boolean类型，所以true、false在where语句中，一定要写成\"true\" ,\"false\" (带双引号) */
	public <T> void deleteByWhere(Class<T> clazz, String where) {
		checkTableExist(clazz);
		execSQL(SQLBuilder.getDeleteSqlByWhere(clazz, where));
	}

	/** 删除表所有元素 */
	public <T> void deleteAll(Class<T> clazz) {
		checkTableExist(clazz);
		execSQL(SQLBuilder.getDeletAllSQL(clazz));
	}

	/** 更新表的某个对象 */
	public void update(Object entity) {
		checkTableExist(entity.getClass());
		execSQL(SQLBuilder.getUpdateSQL(entity));
	}

	/** 更新表的某个对象 */
	public void update(Object entity, String strWhere) {
		checkTableExist(entity.getClass());
		execSQL(SQLBuilder.getUpdateSQLByWhere(entity, strWhere));
	}

	/** 删除表 */
	public <T> void dropTable(Class<T> clazz) {
		checkTableExist(clazz);
		execSQL(SQLBuilder.getDropTableSQL(clazz));

		// 还需要清除TableInfo数据
		TableInfo table = TableInfo.get(clazz);
		table.setCheckDatabese(false);
	}

	public <T> List<T> findAll(Class<T> clazz) {
		return findAllByWhere(clazz, null);
	}

	/**
	 * 根据条件查找所有数据，以id
	 * 
	 * 如果where语句中有limit,请将它放在where末尾
	 * 
	 * @param entity
	 * @return
	 */
	public <T> List<T> findAllByWhere(Class<T> clazz, String where) {
		checkTableExist(clazz);

		String select = SQLBuilder.getSelectSQL(clazz, where);
		debugSql(select);

		List<T> list = new ArrayList<T>();

		Cursor cursor = db.rawQuery(select, null);
		if (cursor != null)
			while (cursor.moveToNext()) {
				try {
					T entity = CursorUtils.getEntity(cursor, clazz);

					list.add(entity);

				} catch (Exception e) {
					e.printStackTrace();
				}
			}

		if (cursor != null)
			cursor.close();
		cursor = null;

		return list;
	}

	public void beginTrancation() {
		db.beginTransaction();
	}

	public void endTrancation() {
		db.setTransactionSuccessful();
		db.endTransaction();
	}

	/** 关闭数据库 */
	public synchronized void closeDB() {
		if (db != null && db.isOpen() && sqliteHelpder != null)
			sqliteHelpder.close();
	}

	/**
	 * 判断某张表是否存在
	 * 
	 * @param tabName
	 *            表名
	 * @return
	 */
	private <T> boolean tableIsExist(Class<T> clazz) {
		TableInfo table = TableInfo.get(clazz);
		if (table.isCheckDatabese()) {
			return true;
		}

		String tabName = ClassUtil.getTableName(clazz);
		boolean result = false;
		if (tabName == null) {
			return false;
		}

		Cursor cursor = null;
		try {
			String sql = "select count(*) as c from sqlite_master where type ='table' and name ='" + tabName.trim() + "' ";
			debugSql(sql);
			cursor = db.rawQuery(sql, null);
			if (cursor.moveToNext()) {
				int count = cursor.getInt(0);
				if (count > 0) {
					result = true;
					table.setCheckDatabese(true);
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (cursor != null)
				cursor.close();
			cursor = null;
		}
		return result;
	}

	/**
	 * 确定table是否存在，不存在则create<br>
	 * 
	 * @param entity
	 */
	private <T> void checkTableExist(Class<T> clazz) {
		if (!tableIsExist(clazz)) {
			String createSQL = SQLBuilder.getCreatTableSQL(clazz);
			execSQL(createSQL);
		}
	}

	/** 调用的时候，判断事务、判断读、写，分别使用getWritableDB和getReadableDB */
	private void execSQL(String sql) {
		if (db == null || (db != null && !db.isOpen())) { // 防止SQLiteDataBase关闭
			db = sqliteHelpder.getWritableDatabase();
		}

		debugSql(sql);
		try {
			db.execSQL(sql);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void execSQL(String sql, Object[] params) {
		if (db == null || (db != null && !db.isOpen())) { // 防止SQLiteDataBase关闭
			db = sqliteHelpder.getWritableDatabase();
		}

		debugSql(sql);
		try {
			db.execSQL(sql, params);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void debugSql(String sql) {
		if (DEBUG)
			Log.d("KK_ORM SQL", sql);
	}
}
